import { commonStyle } from './style';

interface ITemplateHTML {
    id: string;
    style: string;
    render: string;
}

interface IConversionTable {
    cls?: string; // 组件 ClassName
}

interface ISuper {
    selfStyle: string; // 组件样式表
    className: string; // 组件 ClassName
    templateHTML: ITemplateHTML; // 组件内部模板
    conversionTable?: IConversionTable; // 字符串转换表
    registerEvents?: Array<string>; // 注册事件的事件名列表
}

class AutonomousCustomElement extends HTMLElement {
    // ...

    shadow: ShadowRoot;
    conversionTable: IConversionTable | undefined;

    // 事件管理
    eventMap: Record<string, Event>;

    constructor(data: ISuper) {
        super();

        if (!window._webcEvent) {
            window._webcEvent = {};
        }

        this.eventMap = {};
        this.className = data.className;
        this.conversionTable = data.conversionTable;

        this.registerEvent(data.registerEvents);

        this.mountSelfStyle(this.convertMarkCode(data.selfStyle));
        this.shadow = this.attachShadow({ mode: 'open' });

        this.importGlobalResource();
        this.mountCommonStyle();
        this.mountShadowStyle(this.convertMarkCode(data.templateHTML.style));

        const templateEle = this.mountTemplate(data.templateHTML.id, this.convertMarkCode(data.templateHTML.render));
        this.shadow.appendChild(templateEle.content.cloneNode(true));
    }

    /**
     * 注册 Event 事件
     */
    registerEvent(eventArray: Array<string> | undefined): void {
        if (eventArray) {
            for (const eventStr of eventArray) {
                const event = new CustomEvent(eventStr, { bubbles: false, cancelable: true });
                this.eventMap[eventStr] = event;
            }
        }
    }

    /**
     * 转换字符串中的标识符
     */
    convertMarkCode(content: string): string {
        if (this.conversionTable) {
            for (const key in this.conversionTable) {
                const reg = new RegExp(`{${key}}`, 'g');
                content = content.replace(reg, (this.conversionTable as Record<string, string>)[key]);
            }
        }
        return content;
    }

    /**
     * 为自身挂载样式
     */
    mountSelfStyle(styleContent: string): void {
        const style = document.createElement('style');
        style.textContent = styleContent;
        this.appendChild(style);
    }

    /**
     * 为 shadow root 挂载样式
     */
    mountShadowStyle(styleContent: string): void {
        const style = document.createElement('style');
        style.textContent = styleContent;
        this.shadow.appendChild(style);
    }

    /**
     * 为内部引入公共样式
     */
    mountCommonStyle(): void {
        const style = document.createElement('style');
        style.textContent = commonStyle;
        this.shadow.appendChild(style);
    }

    /**
     * 为内部引入全局的 Link 资源
     */
    importGlobalResource(): void {
        const linkEles = document.querySelectorAll('link');
        linkEles.forEach(linkEle => {
            if (linkEle.getAttribute('data-webc-link')?.includes('inner')) {
                this.shadow.appendChild(linkEle.cloneNode(false));
            }
        });
    }

    /**
     * 在 HTML 文档上挂载模板
     */
    mountTemplate(templateId: string, templateInner: string): HTMLTemplateElement {
        const templateEle = document.querySelector(`#${templateId}`);

        if (templateEle) {
            return templateEle as HTMLTemplateElement;

            // ...
        } else {
            const templateEle = document.createElement('template');

            templateEle.id = templateId;
            templateEle.innerHTML = templateInner;

            document.body.appendChild(templateEle);

            return templateEle;
        }
    }
}

export { AutonomousCustomElement };
